package com.mccken.annotation.hystrix.value.impl;

import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;

import com.mccken.annotation.DoHystrix;
import com.mccken.annotation.hystrix.value.IValueService;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixThreadPoolProperties;

import cn.hutool.json.JSONUtil;

/**
 * @program: mccken-collect
 * @description:
 * @author: mccken
 * @create: 2022-12-24 15:15
 **/
public class HystrixValueImpl extends HystrixCommand<Object> implements IValueService {
	
	private ProceedingJoinPoint jp;
	private Method method;
	private DoHystrix doHystrix;
	
	public HystrixValueImpl() {

		/**
		 * 配置HystrixCommand属性
		 * GroupKey:                该命令属于哪一个组，可以帮助我们更好的组织命令
		 * CommandKey:              该命令的名称
		 * ThreadPoolKey:           该命令所属的线程池，同样配置的命令会共享同一线程池。若不配置，会默认使用GroupKey作为线程池名称
		 * CommandProperties:       该命令的一些设置，包括断路器的配置，隔离策略，降级策略，以及一些监控指标等
		 * ThreadPoolProperties:    关于线程池的配置，包括线程池大小，排队队列的大小等
		 */
		super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("GovernGroup"))
				.andCommandKey(HystrixCommandKey.Factory.asKey("GovernKey"))
				.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
						.withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD))
				.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(10))
		);
	}

	@Override
	protected Object run() throws Exception {
		try {
			return jp.proceed();
		} catch (Throwable e) {
			return null;
		}
	}

	@Override
	public Object access(ProceedingJoinPoint jp, Method method, DoHystrix doHystrix, Object[] args) {
		this.jp = jp;
		this.method = method;
		this.doHystrix = doHystrix;
		
		Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("GovernGroup"))
				.andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(doHystrix.timeoutValue()));
		
		return this.execute();
	}

	@Override
	protected Object getFallback() {
		return JSONUtil.toBean(doHystrix.returnJson(), method.getReturnType());
	}
}
